#!/usr/bin/perl
#
#       gen_db.pl
#
# Utility script to scan music directory and load song data
# into a sqlite database.
#
#


use strict;
use warnings;

use File::Find::Rule;
use Ogg::Vorbis::Header::PurePerl;
use MP3::Tag;
use DBI;
use Encode;
use Digest;


sub get_mp3_tags {
    my $mp3 = MP3::Tag->new(shift);
    my $tags = $mp3->autoinfo();
    $tags->{duration} = int $mp3->total_secs();
    return utf8ize($tags);
}

sub get_vorbis_tags {
    my $ogg = Ogg::Vorbis::Header::PurePerl->new(shift);
    my $tags = {};

    $tags->{artist}   = $ogg->comment('artist');
    $tags->{title}    = $ogg->comment('title');
    $tags->{album}    = $ogg->comment('album');
    $tags->{duration} = $ogg->info->{length};
    return utf8ize($tags);
}

sub insert_track {
    my ($dbh, $t) = @_;
    my $sth = $dbh->prepare("INSERT OR IGNORE INTO tracks (artist, title, album, length, path, digest) " .
                            "VALUES (:1, :2, :3, :4, :5, :6)");
    $sth->execute($t->{artist}, $t->{title}, $t->{album}, $t->{duration}, $t->{path}, $t->{digest}); 
    $sth->finish;

}

sub utf8ize {
    my %tags = %{ $_[0] };
    for my $k ( keys %tags ) {
        $tags{$k} = decode_utf8($tags{$k}); 
    }
    return \%tags;

}
binmode STDOUT, ":utf8";
my $MUSIC_DIR = '/home/o0/mpd/music/';
my $finder = File::Find::Rule->new;
my @files = File::Find::Rule->file()
                             ->name( '*.mp3', '*.ogg' )
                             ->in( $MUSIC_DIR );
my $target_db = pop @ARGV;
$target_db ||= "song_db.sqlite";
[ -e $target_db ] and unlink $target_db;

my $create_statement =<<FIN;
create table tracks(
    id INTEGER PRIMARY KEY,
    artist TEXT NOT NULL COLLATE NOCASE,
    title TEXT NOT NULL COLLATE NOCASE,
    album TEXT NOT NULL COLLATE NOCASE,
    length INTEGER NOT NULL,
    path TEXT NOT NULL,
    digest TEXT NOT NULL);
FIN

our $dbh = DBI->connect("dbi:SQLite:dbname=$target_db", "", "", {RaiseError => 1})
    or die $DBI::errstr;

$dbh->do($create_statement);


for my $track (@files) {
    my ($ext) = $track =~ /.*\.(.+)$/;
    my $tags = undef;

    lc $ext eq 'mp3' and $tags = get_mp3_tags($track);
    lc $ext eq 'ogg' and $tags = get_vorbis_tags($track);
    ($tags->{path}) = $track =~ /^$MUSIC_DIR(.*)/;
    !defined $tags->{album} and $tags->{album} = '';

    my $digest = Digest->new('MD5');
    open my $fd, '<', $track;
    $digest->addfile($fd);
    $tags->{digest} = $digest->b64digest;

    print $tags->{artist} . " - " . $tags->{title} . " (" . $tags->{album} . ") " . $tags->{duration} . " - " . $tags->{digest} . "\n";
    insert_track($dbh, $tags);
}

$dbh->disconnect;

